﻿using System;
using System.Collections.Generic;
//using System.Linq;
//using System.Text;

using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;

namespace ZIP
{
    class ZIP
    {
        private static void WriteZipFile(List<string> filesToZip, string path, int compression)
        {
            if (compression < 0 || compression > 9)
                throw new ArgumentException("Invalid compression rate.");

            if (!Directory.Exists(new FileInfo(path).Directory.ToString()))
                throw new ArgumentException("The Path does not exist.");

            foreach (string c in filesToZip)
                if (!File.Exists(c))
                    throw new ArgumentException(string.Format("The File{0}does not exist!", c));

            Crc32 crc32 = new Crc32();
            ZipOutputStream stream = new ZipOutputStream(File.Create(path));
            stream.SetLevel(compression);


            for (int i = 0; i < filesToZip.Count; i++)
            {
                ZipEntry entry = new ZipEntry(Path.GetFileName(filesToZip[i]));
                entry.DateTime = DateTime.Now;

                entry.CompressionMethod = CompressionMethod.Deflated;

                using (FileStream fs = File.OpenRead(filesToZip[i]))
                {
                    byte[] buffer = new byte[fs.Length];

                    int readedBits;
                    readedBits = fs.Read(buffer, 0, buffer.Length);
                    int eSize = readedBits;
                    while (readedBits > 0)
                    {
                        readedBits = fs.Read(buffer, readedBits, buffer.Length - readedBits);
                        eSize += readedBits;
                    }

                    entry.Size = eSize;

                    fs.Close();
                    crc32.Reset();
                    crc32.Update(buffer);
                    entry.Crc = crc32.Value;
                    stream.PutNextEntry(entry);
                    stream.Write(buffer, 0, buffer.Length);
                }
            }
            stream.Finish();
            stream.Close();
        }

        private static void UncompressZip(string sFile)
        {
            ZipInputStream zipIn = new ZipInputStream(File.OpenRead(sFile));
            ZipEntry entry;
            while ((entry = zipIn.GetNextEntry()) != null)
            {
                FileStream streamWriter = File.Create(entry.Name);
                long size = entry.Size;
                byte[] data = new byte[size];
                while (true)
                {
                    size = zipIn.Read(data, 0, data.Length);
                    if (size > 0) streamWriter.Write(data, 0, (int)size);
                    else break;
                }
                streamWriter.Close();
            }
            Console.WriteLine("Done!!");
        }


        static void Main(string[] args)
        {

            int choice;
            Console.WriteLine("Enter 1 for ZIPping and 0 for unZIPping");
            choice = int.Parse(Console.ReadLine());
            switch (choice)
            {
                case 1:
                    Console.WriteLine("Enter name of the file to be ziped");
                    string inputFile = Console.ReadLine();
                    string outputFile = inputFile + ".zip";
                    List<string> inputFiles = new List<string>();
                    inputFiles.Add(inputFile);
                    WriteZipFile(inputFiles, outputFile, 9);
                    break;

                case 0:
                    Console.WriteLine("Enter name of the zip file");
                    UncompressZip(Console.ReadLine());
                    break;

                default:
                    Console.WriteLine("Invalid Choice");
                    break;
            }
        }
    }
}
